package com.xpc.consumer.spring.scanner.reference;

import com.xpc.consumer.spring.config.RpcConsumerAutoConfig;
import com.xpc.consumer.spring.scanner.ClassScanner;
import com.xpc.rpc.annotation.DubboReference;
import com.xpc.rpc.consumer.RpcConsumer;
import com.xpc.rpc.proxy.jdk.JdkProxy;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.util.List;

public class ReferenceScanner extends ClassScanner {

    private static final Logger LOGGER = LoggerFactory.getLogger(ReferenceScanner.class);

    public void doScanDubboReferenceByPackage(String packageName) throws Exception{
        if(StringUtils.isEmpty(packageName)) {
            throw new RuntimeException("scan packageName is empty");
        }
        List<String> classList = getClassList(packageName);
        if(classList == null || classList.isEmpty()) {
            return;
        }
        classList.forEach(item -> {
            try {
                Class<?> clazz = Class.forName(item);
                Field[] clazzFields = clazz.getDeclaredFields();
                for(Field field : clazzFields) {
                    DubboReference dubboReference = field.getAnnotation(DubboReference.class);
                    if(dubboReference != null) {
                        Class<?> targetClazz = field.getType();
                        JdkProxy jdkProxy = new JdkProxy(RpcConsumer.getInstance(),dubboReference.serializationType());
                        Object proxy = jdkProxy.getProxy(targetClazz);
                        setField(field, RpcConsumerAutoConfig.getObject(clazz),proxy,true);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }
    /**
     * 设置类的属性值
     *
     * @param field 成员变量
     * @param target 类实例
     * @param value  成员变量的值
     * @param accessible 是否允许设置私有属性
     */
    public static void setField(Field field, Object target, Object value,boolean accessible){
        try {
            //是否允许设置私有的成员变量的值
            field.setAccessible(accessible);
            field.set(target,value);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

}
